package org.jetlinks.community.mstn.web;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.hswebframework.ezorm.core.param.Sort;
import org.hswebframework.ezorm.core.param.Term;
import org.hswebframework.web.api.crud.entity.PagerResult;
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
import org.hswebframework.web.authorization.annotation.Authorize;
import org.hswebframework.web.authorization.annotation.Resource;
import org.hswebframework.web.crud.service.ReactiveCrudService;
import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController;
import org.jetlinks.community.auth.entity.OrganizationEntity;
import org.jetlinks.community.device.service.AssetsService;
import org.jetlinks.community.mstn.entity.CustomFormEntity;
import org.jetlinks.community.mstn.entity.CustomFormLogEntity;
import org.jetlinks.community.mstn.entity.vo.SiteListResVO;
import org.jetlinks.community.mstn.enums.FormType;
import org.jetlinks.community.mstn.service.CustomFormService;
import org.jetlinks.community.mstn.term.MstnAssetsTermBuilder;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 自定义表单
 *
 */
@RestController
@RequestMapping("/form")
@Authorize
@Resource(id = "form", name = "自定义表单", group = "mstn")
@Tag(name = "自定义表单")
@AllArgsConstructor
public class CustomFormController implements ReactiveServiceCrudController<CustomFormEntity, String> {

    private final CustomFormService customFormService;

    private final AssetsService assetsService;


    @Override
    public ReactiveCrudService<CustomFormEntity, String> getService() {
        return customFormService;
    }

    /**
     * 上报数据
     * @param customFormLogEntity
     * @return
     */
    @PostMapping("/upload/data/{formId}")
    @Authorize(merge = false)
    @Operation(summary = "上报数据")
    public Mono<Void> uploadData(@PathVariable String formId,
                                 @RequestBody CustomFormLogEntity customFormLogEntity){
        return customFormService.saveUploadData(formId,customFormLogEntity);
    }

    @PostMapping("/query/data/{formId}")
    @Authorize(merge = false)
    @Operation(summary = "获取数据byId +项目id")
    public Mono<CustomFormLogEntity> queryData(@PathVariable String formId,
                                                @RequestBody QueryParamEntity query) {
        return customFormService.queryUploadData(formId, query)
            .collectList()
            .flatMap(list -> {
                if (!list.isEmpty()) {
                    return Mono.just(list.get(0));
                }
                return Mono.empty();
            });
    }
    @GetMapping("/query/data/{formId}/{logId}")
    @Authorize(merge = false)
    @Operation(summary = "查询数据")
    public Mono<CustomFormLogEntity> queryData(@PathVariable String formId,
                                               @PathVariable String logId) {
        return customFormService.queryUploadDataById(formId, logId);
    }

    @DeleteMapping("/del/data/{formId}/{logId}")
    @Authorize(merge = false)
    @Operation(summary = "删除数据")
    public Mono<Long> deleteData(@PathVariable String formId,
                                 @PathVariable String logId) {
        return customFormService.deleteUploadDataById(formId, logId);
    }
    @PutMapping("/update/data/{formId}")
    @Authorize(merge = false)
    @Operation(summary = "修改数据")
    public Mono<Void> updateData(@PathVariable String formId,@RequestBody CustomFormLogEntity customFormLogEntity) {
        return customFormService.updateUploadData(formId, customFormLogEntity);
    }


    @PostMapping("/{parentId}/{userId}")
    @Authorize(merge = false)
    @Operation(summary = "获取站点列表[带logId]")
    public Mono<PagerResult<SiteListResVO>> getTypeList(
        @PathVariable String parentId,
        @PathVariable String userId,
        @RequestBody Mono<QueryParamEntity> query) {

        QueryParamEntity formQuery = new QueryParamEntity();
        Sort sort = new Sort();
        sort.setOrder("asc");
        sort.setName("createTime");
        List <Sort> sorts = new ArrayList<>();
        sorts.add(sort);
        formQuery.setSorts(sorts);
        formQuery.setPaging(false);
        Term term = new Term();
        term.setColumn("id");
        term.setValue(parentId);
        term.setTermType(MstnAssetsTermBuilder.assetsType);

        Term typeTerm = new Term();
        typeTerm.setColumn("type");
        typeTerm.setValue(FormType.siteInfo);

        List <Term> terms = new ArrayList<>();
        terms.add(term);
        terms.add(typeTerm);
        formQuery.setTerms(terms);
        return customFormService.query(formQuery).collectList().flatMap(
            list -> {
                if (list.isEmpty()) {
                    return Mono.just(new PagerResult<>(0, new ArrayList<>()));
                }

                return Mono.just(list.get(0).getId())
                    .flatMap(formId ->
                        customFormService
                            .getSiteList(parentId, query)
                            .flatMap(pagerResult ->
                                customFormService
                                    .queryUploadData(formId,pagerResult.getData().stream().map(OrganizationEntity::getId).collect(Collectors.toList()))
                                    .collectMap(CustomFormLogEntity::getOrgId)
                        .           flatMap(orgIdMap -> {
                                        List<SiteListResVO> siteList = pagerResult
                                        .getData()
                                        .stream()
                                        .map(SiteListResVO::of)
                                        .peek(siteListResVO -> {
                                            if (orgIdMap.containsKey(siteListResVO.getId())) {
                                                siteListResVO.setLogId(orgIdMap.get(siteListResVO.getId()).getId());
                                            }
                                        })
                                        .collect(Collectors.toList());
                                return Mono.just(PagerResult.of(pagerResult.getTotal(), siteList));
                        })));
            }
        );
    }

}
